package ru.nsu.fit.iconveyor.engine;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Abstract realization of Engine which implements working with observers
 */
public abstract class AbstractEngine implements Engine {
    private List<EngineStateObserver> engineStateObservers = new ArrayList<EngineStateObserver>();
    private List<ConveyorExecutionObserver> conveyorExecutionObservers = new ArrayList<ConveyorExecutionObserver>();

    @Override
    public void addEngineStateObserver(EngineStateObserver observer) {
        if(observer == null) {
            throw new IllegalArgumentException("observer can not be null");
        }
        engineStateObservers.add(observer);
    }

    @Override
    public void removeEngineStateObserver(EngineStateObserver observer) {
        engineStateObservers.remove(observer);
    }

    @Override
    public void addConveyorExecutionObserver(ConveyorExecutionObserver observer) {
        if(observer == null) {
            throw new IllegalArgumentException("observer can not be null");
        }
        conveyorExecutionObservers.add(observer);
    }

    @Override
    public void removeConveyorExecutionObserver(ConveyorExecutionObserver observer) {
        conveyorExecutionObservers.remove(observer);
    }

    protected void notifyEngineStateObserversOnStart() {
        for(EngineStateObserver observer : engineStateObservers) {
            observer.onStart();
        }
    }

    protected void notifyEngineStateObserversOnFinish() {
        for(EngineStateObserver observer : engineStateObservers) {
            observer.onFinish();
        }
    }

    protected void notifyEngineStateObserversOnStop() {
        for(EngineStateObserver observer : engineStateObservers) {
            observer.onStop();
        }
    }

    protected void notifyEngineStateObserversOnError(Exception cause, boolean stopped) {
        for(EngineStateObserver observer : engineStateObservers) {
            observer.onError(cause, stopped);
        }
    }

    protected void notifyConveyorExecutionObserversOnNodeExecuted(String nodeId, Collection<String> affectedInputs, Collection<String> affectedOutputs) {
        for(ConveyorExecutionObserver observer : conveyorExecutionObservers) {
            observer.onNodeExecuted(nodeId, affectedInputs, affectedOutputs);
        }
    }
}
